package com.jsjvm.server.dbgproxy.jdwp.data;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

import com.jsjvm.shared.jdwp.data.JDWPLocation;


/**
 * InputStream that reads JDWP specific datatypes.
 * 
 * @author ctalau
 * 
 */
public class JDWPInputStream {
	ByteArrayInputStream bais = null;
	DataInputStream dis = null;
	
	DataInputStream in;
	
	
	public JDWPInputStream(InputStream in) {
		this.in = new DataInputStream(in);
	}

	public JDWPRequestHeader readPacket() throws IOException {
		int length = in.readInt();
		int id = in.readInt();
		byte flags = in.readByte();
		byte commandSet = in.readByte();
		byte command = in.readByte();

		if (flags != 0x00)
			return null;
		
		// build the packet buffer from which one can read the fields
		byte[] buf = new byte[length - 11];
		in.read(buf);
		bais = new ByteArrayInputStream(buf);
		dis = new DataInputStream(bais);
		
		return new JDWPRequestHeader(length, id, commandSet, command);
	}
	
	public int readID() throws IOException {
		return dis.readInt();
	}

	public int readTaggedID() throws IOException {
		dis.read();
		return dis.readInt();
	}

	public JDWPLocation readLocation() throws IOException {
		dis.read();
		int classID = dis.readInt();
		int methodID = dis.readInt();
		long location = dis.readLong();

		return new JDWPLocation(classID, methodID, location);
	}

	public Object readValue(int tag) throws IOException {
		switch (tag) {
		case JDWPTag.ARRAY_TAG:
		case JDWPTag.OBJECT_TAG:
		case JDWPTag.STRING_TAG:
		case JDWPTag.THREAD_TAG:
		case JDWPTag.THREAD_G_TAG:
		case JDWPTag.CLASS_LOAD_TAG:
		case JDWPTag.CLASS_TAG:
			return readID();
		case JDWPTag.BYTE_TAG:
			return dis.readByte();
		case JDWPTag.CHAR_TAG:
			return dis.readChar();
		case JDWPTag.FLOAT_TAG:
			return dis.readFloat();
		case JDWPTag.DOUBLE_TAG:
			return dis.readDouble();
		case JDWPTag.INT_TAG:
			return dis.readInt();
		case JDWPTag.LONG_TAG:
			return dis.readLong();
		case JDWPTag.SHORT_TAG:
			return dis.readShort();
		case JDWPTag.BOOLEAN_TAG:
			return dis.readByte();
		}
		return null;
	}

	public Object readTaggedValue() throws IOException {
		int tag = dis.read();
		return readValue(tag);
	}

	public String readString() throws IOException {
		int length = dis.readInt();
		byte buf[] = new byte[length];
		dis.read(buf);
		return new String(buf);
	}

	public Object[] readArrayRegion() {
		throw new UnsupportedOperationException();
	}

	public byte readByte() throws IOException{
		return dis.readByte();
	}
	
	public int readInt() throws IOException{
		return dis.readInt();
	}
	
	
	public void read(byte [] buf) throws IOException{
		in.read(buf);
	}
}
